Basic Library for UWP
オンデマンドの読み込み
Basic Library for UWP > TreeView for UWP > TreeView の動作 > オンデマンドの読み込み

アプリケーションの起動時に各ノードをすべて生成するのではなく、ユーザーがノードを展開すると、オンデマンドでノードにデータが挿入される遅延ロードという技術を使用することができます。これにより、アプリケーションの読み込み速度が向上し、リソースを効率よく使用できます。

ノードの遅延ロードを実装するには、次のコードを使用します。

Visual Basic コードの書き方

Visual Basic
コードのコピー
Public Sub New()
InitializeComponent()
' ここは変更しません
' ...
' C1TreeView を初期化します
InitializeTreeView()
End Sub
Private Sub InitializeTreeView()
' 設計時に追加された項目を削除します
_tv.Items.Clear()
' アセンブリ内のすべての型をスキャンします
For Each t As Type In _tv.[GetType]().Assembly.GetTypes()
        If t.IsPublic AndAlso Not t.IsSpecialName AndAlso Not t.IsAbstract Then
               ' この型のノードを追加します
               Dim node As New C1TreeViewItem()
               node.Header = t.Name
               node.FontWeight = FontWeights.Bold
               _tv.Items.Add(node)
               ' プロパティ、イベント、およびメソッドのサブノードを追加します
               node.Items.Add(CreateMemberNode("Properties", t, MemberTypes.[Property]))
               node.Items.Add(CreateMemberNode("Events", t, MemberTypes.[Event]))
               node.Items.Add(CreateMemberNode("Methods", t, MemberTypes.Method))
        End If
Next
End Sub
Private Function CreateMemberNode(header As String, memberTypes As MemberTypes) As C1TreeViewItem
' ノードを作成します
Dim node As New C1TreeViewItem()
node.Header = header
node.Foreground = New SolidColorBrush(Colors.DarkGray)
' ノードを展開する前にノードにデータを挿入するためのイベントハンドラを登録します
AddHandler node.Expanding, AddressOf node_Expanding
' ノードにデータを挿入するために必要な情報を保存します
node.Tag = memberTypes
' このノードを展開できるように、ダミーノードを追加します
node.Items.Add(New C1TreeViewItem())
node.IsExpanded = False
' 終了します
Return node
End Function
'ノードにデータを挿入します
Private Sub node_Expanding(sender As Object, e As RoutedEventArgs)
' イベントが発生したノードを取得します
Dim node As C1TreeViewItem = TryCast(sender, C1TreeViewItem)
' イベントハンドラの登録を解除します(ノードにデータを挿入したら、このハンドラは不要になります)
RemoveHandler node.Expanding, AddressOf node_Expanding
' ダミーノードを削除します
node.Items.Clear()
' ノードにデータを挿入します
Dim type As Type = DirectCast(node.Parent.Tag, Type)
Dim memberTypes As MemberTypes = DirectCast(node.Tag, MemberTypes)
Dim bf As BindingFlags = BindingFlags.[Public] Or BindingFlags.Instance
For Each mi As MemberInfo In type.GetMembers(bf)
        If mi.MemberType = memberTypes Then
               If Not mi.Name.StartsWith("get_") AndAlso Not mi.Name.StartsWith("set_") Then
                       Dim item As New C1TreeViewItem()
                       item.Header = mi.Name
                       item.FontSize = 12
                       node.Items.Add(item)
               End If
        End If
Next
End Sub

C# コードの書き方

C#
コードのコピー
public Page()
{
    InitializeComponent();
    // ここは変更しません
    // ...
    // C1TreeView を初期化します
    InitializeTreeView();           
}
void InitializeTreeView()
{
  // 設計時に追加された項目を削除します
  _tv.Items.Clear();
   // アセンブリ内のすべての型をスキャンします
  foreach (Type t in _tv.GetType().Assembly.GetTypes())
  {
    if (t.IsPublic && !t.IsSpecialName && !t.IsAbstract)
    {
      // この型のノードを追加します
      C1TreeViewItem node = new C1TreeViewItem();
      node.Header = t.Name;
      node.FontWeight = FontWeights.Bold;
      _tv.Items.Add(node);
      // プロパティ、イベント、およびメソッドのサブノードを追加します
      node.Items.Add(CreateMemberNode("Properties", t, MemberTypes.Property));
      node.Items.Add(CreateMemberNode("Events", t, MemberTypes.Event));
      node.Items.Add(CreateMemberNode("Methods", t, MemberTypes.Method));
    }
  }
}
C1TreeViewItem CreateMemberNode(string header, MemberTypes memberTypes)
{
  // ノードを作成します
  C1TreeViewItem node = new C1TreeViewItem();
  node.Header = header;
  node.Foreground = new SolidColorBrush(Colors.DarkGray);
   // ノードを展開する前にノードにデータを挿入するためのイベントハンドラを登録します
  node.Expanding += node_Expanding;
   // ノードにデータを挿入するために必要な情報を保存します
  node.Tag = memberTypes;
   // このノードを展開できるように、ダミーノードを追加します
  node.Items.Add(new C1TreeViewItem());
  node.IsExpanded = false;
   // 終了します
  return node;          
}
//ノードにデータを挿入します
void node_Expanding(object sender, RoutedEventArgs e)
{
  // イベントが発生したノードを取得します
  C1TreeViewItem node = sender as C1TreeViewItem;
  // イベントハンドラの登録を解除します(ノードにデータを挿入したら、このハンドラは不要になります)
  node.Expanding -= node_Expanding;
   // ダミーノードを削除します
  node.Items.Clear();
   // ノードにデータを挿入します
  Type type = (Type)node.Parent.Tag;
  MemberTypes memberTypes = (MemberTypes)node.Tag;
   BindingFlags bf = BindingFlags.Public | BindingFlags.Instance;
  foreach (MemberInfo mi in type.GetMembers(bf))
  {
    if (mi.MemberType == memberTypes)
    {
      if (!mi.Name.StartsWith("get_") && !mi.Name.StartsWith("set_"))
      {
        C1TreeViewItem item = new C1TreeViewItem();
        item.Header = mi.Name;
        item.FontSize = 12;
        node.Items.Add(item);
      }
    }
  }       
}

この実装は、ユーザーがノードを展開しようとしたときに、ノードにデータを挿入できるように、Expanding イベントのイベントハンドラを登録します。Tag プロパティには、ノードにデータを挿入するために必要な情報を保存します。最後に、ユーザーがこのノードを展開して、ノードにデータを挿入する Expanding イベントをトリガできるように、ダミーの子ノードを追加します。

Tag プロパティを使用する代わりに、C1TreeViewItem からカスタムクラスを継承し、そのクラスにすべての遅延ロードロジックを組み込むこともできるはずです。その方が洗練された方法ですが、ではテンプレートの継承がサポートされていません。テンプレートを持つクラス(Button、C1TreeViewItem など)からクラスを継承しても、テンプレートは継承されないため、テンプレートを各自で提供する必要があります。そうしないと、その派生クラスは単に空のコントロールになります。

関連トピック